package cn.lizemin.fakedata.security.filters;

import cn.lizemin.fakedata.common.RespBean;
import cn.lizemin.fakedata.common.ResultEnum;
import cn.lizemin.fakedata.constant.SecurityConstant;
import cn.lizemin.fakedata.security.SecurityContextHolder;
import cn.lizemin.fakedata.security.UserDetails;
import cn.lizemin.fakedata.utils.JSON;
import cn.lizemin.fakedata.utils.SecurityUtil;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Objects;

/**
 * @author lzm
 * @Date 2024/7/7
 * @description
 */
@WebFilter("/*")
@Component // 一定要加这个注解，因为只有spring中的bean才能够通过ordered接口或者@order注解来控制filter的执行顺序
@Order(1)
public class TokenFilter extends OncePerRequestFilter {

    private static final Logger log = LoggerFactory.getLogger(TokenFilter.class);

    /**
     * 校验用户的请求是否携带了token
     */
    @Override
    protected void doFilterInternal(HttpServletRequest req, HttpServletResponse response, FilterChain chain) throws ServletException, IOException {
        log.info("开始校验用户是否携带了token");
        if (SecurityUtil.validateRequest(req)) {
            chain.doFilter(req, response);
            return;
        }
        HttpServletResponse resp = SecurityUtil.toHttpServletResponse(response);
        String token = "";
        Cookie[] cookies = req.getCookies();
        if (cookies != null) {
            for (Cookie cookie : cookies) {
                if (SecurityConstant.TOKEN_NAME.equals(cookie.getName())) {
                    token = cookie.getValue();
                }
            }
        }
        if (StringUtils.isBlank(token)) {
            try (PrintWriter writer = resp.getWriter()) {
                RespBean respBean = RespBean.fail(ResultEnum.USER_NOT_AUTHENTICATED);
                writer.write(JSON.toJson(respBean));
                return;
            }
        }
        HttpSession session = req.getSession();
        // 校验token
        UserDetails user = (UserDetails) session.getAttribute(token);
        if (Objects.isNull(user)) {
            try (PrintWriter writer = resp.getWriter()) {
                RespBean respBean = RespBean.fail(ResultEnum.USER_NOT_AUTHENTICATED);
                writer.write(JSON.toJson(respBean));
                return;
            }
        }
        SecurityContextHolder.setCurrentUser(user);
        chain.doFilter(req, response);
    }

}
